package cn.smile.business.core.impl;

import cn.smile.bean.entity.core.ReqWithoutInfo;
import cn.smile.bean.form.core.without.ReqWithoutAddForm;
import cn.smile.business.core.IReqWithoutService;
import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.domain.BaseServiceImpl;
import cn.smile.repository.core.ReqWithoutInfoMapper;
import cn.smile.utils.BeanCopy;
import cn.smile.utils.DateFormatUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author smile-jt
 */
@Slf4j
@Service
public class ReqWithoutServiceImpl extends BaseServiceImpl<ReqWithoutInfoMapper, ReqWithoutInfo> implements IReqWithoutService {

    @Resource
    private RestTemplate restTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addInfo(ReqWithoutAddForm form) {
        log.info("[ReqWithoutServiceImpl].[addInfo] ------> 新增外部接口请求记录 开始, form = {}", JSON.toJSONString(form));
        ReqWithoutInfo entity = BeanCopy.copyBean(form, ReqWithoutInfo.class);
        super.addBaseCol(entity);
        int insertNum = baseMapper.insert(entity);
        log.info("[ReqWithoutServiceImpl].[addInfo] ------> 新增外部接口请求记录 结束, insertNum = {}", insertNum);
        return insertNum > NumberConstant.ZERO;
    }

    @Override
    public String reqWithOutUrl(String url, Map<String, Object> params, HttpMethod method, Boolean isRec) {
        return this.reqWithOutUrl(url, params, method, String.class, isRec);
    }

    @Override
    public String reqWithOutUrlByForm(String url, MultiValueMap<String, Object> params, HttpMethod method) {
        log.info("[ReqWithoutServiceImpl].[reqWithOutUrlByForm] ------> 请求外部接口 开始, url = {}, params = {}", url, JSON.toJSONString(params));
        //组装请求头及请求参数
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, Object>> httpEntitys = new HttpEntity<>(params, headers);
        ResponseEntity<String> response = restTemplate.exchange(url, method, httpEntitys, String.class);
        log.info("[ReqWithoutServiceImpl].[reqWithOutUrlByForm] ------> 请求外部接口 结束, response.getBody() = {}", response.getBody());
        return response.getBody();
    }

    @Override
    public void taskDelInfo(Date endDate) {
        String datetime = DateFormatUtil.parseDateToStr(endDate, DateFormatUtil.DATE_TIME_FORMAT_1);
        log.info("[ReqWithoutServiceImpl].[taskDelInfo] ------> 删除过期日志 Start, endDate = {}", datetime);
        List<ReqWithoutInfo> baseList = baseMapper.selectList(new QueryWrapper<ReqWithoutInfo>().lambda().le(ReqWithoutInfo::getReqTime, datetime));
        int delNum = NumberConstant.ZERO;
        if (!CollectionUtils.isEmpty(baseList)) {
            for (ReqWithoutInfo entity : baseList) {
                delNum += baseMapper.deleteById(entity);
            }
        }
        log.info("[ReqWithoutServiceImpl].[taskDelInfo] ------> 删除过期日志 End, delNum = {}", delNum);
    }

    @Override
    public <T> T reqWithOutUrl(String url, Map<String, Object> params, HttpMethod method, Class<T> clazz, Boolean isRec) {
        return this.runWithoutReq(url, params, method, clazz, isRec).getBody();
    }

    /**
     * 执行外部请求
     *
     * @param url    请求URL
     * @param params 请求参数
     * @param method 请求方式
     * @param clazz  接收返回的Class
     * @param <T>    接收返回的泛型
     * @return 请求结果
     */
    private <T> ResponseEntity<T> runWithoutReq(String url, Map<String, Object> params, HttpMethod method, Class<T> clazz, Boolean isRec) {
        log.info("[ReqWithoutServiceImpl].[runWithoutReq] ------> 请求外部接口 开始, url = {}, params = {}", url, JSON.toJSONString(params));
        //组装请求头及请求参数
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        //组装记录参数
        ReqWithoutAddForm form = new ReqWithoutAddForm();
        this.setAddFormReq(form, url, JSON.toJSONString(headers), JSON.toJSONString(params));
        ResponseEntity<T> response;
        if (HttpMethod.GET == method) {
            HttpEntity<Map<String, Object>> httpEntitys = new HttpEntity<>(headers);
            response = restTemplate.exchange(url, method, httpEntitys, clazz, params);
        } else {
            HttpEntity<Map<String, Object>> httpEntitys = new HttpEntity<>(params, headers);
            response = restTemplate.exchange(url, method, httpEntitys, clazz);
        }
        boolean respFlag = response.getStatusCode().value() == NumberConstant.TWO_HUNDRED;
        this.setAddFormResp(form, respFlag, response.getBody());
        if (isRec) {
            //noinspection SpringTransactionalMethodCallsInspection
            this.addInfo(form);
        }
        log.info("[ReqWithoutServiceImpl].[runWithoutReq] ------> 请求外部接口 结束, response.getBody() = {}", response.getBody());
        return response;
    }

    /**
     * 写入请求信息
     *
     * @param form         新增对象
     * @param url          请求url
     * @param headerString 请求头信息
     * @param bodyString   请求对象信息
     */
    private void setAddFormReq(ReqWithoutAddForm form, String url, String headerString, String bodyString) {
        if (ObjectUtils.isEmpty(form)) {
            form = new ReqWithoutAddForm();
        }
        form.setUrl(url);
        form.setReqHeader(headerString);
        form.setReqBody(bodyString);
        form.setReqTime(LocalDateTime.now());
    }

    /**
     * 写入响应信息
     *
     * @param form       新增对象
     * @param respFlag   请求头信息
     * @param respResult 请求对象信息
     */
    private void setAddFormResp(ReqWithoutAddForm form, boolean respFlag, Object respResult) {
        if (ObjectUtils.isEmpty(form)) {
            form = new ReqWithoutAddForm();
        }
        form.setRespFlag(respFlag);
        form.setRespResult(respResult.toString());
        form.setRespTime(LocalDateTime.now());
    }
}
